package interfaces.spawnMenu.costumize.hunters;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import interfaces.GUISource;
import interfaces.ImageUpdater;
import interfaces.spawnMenu.costumize.CustomizeContainer;
import interfaces.spawnMenu.costumize.CustomizeWindow;
import interfaces.superWidgets.HorizontalScrollContent;
import interfaces.superWidgets.InterfaceButton;
import logic.common.player.Player;
import logic.common.team.Fraction;
import logic.common.team.Team;
import logic.nodes.collision.DummyType;
import logic.nodes.lod.BBNodeController;
import logic.ships.hunter.Hunter;
import logic.ships.hunter.HunterProperties;
import main.InitGame;
import main.listeners.listenerClasses.LanguageListener;

import org.fenggui.binding.render.ImageFont;
import org.fenggui.event.ButtonPressedEvent;
import org.fenggui.event.IButtonPressedListener;
import org.fenggui.event.key.Key;
import org.fenggui.event.mouse.MouseButton;
import org.fenggui.event.mouse.MouseClickedEvent;
import org.fenggui.event.mouse.MousePressedEvent;
import org.fenggui.event.mouse.MouseReleasedEvent;
import org.fenggui.util.Color;

import factories.HunterFactory;
import fileHandling.language.Lang;
import fileHandling.language.LanguageLoader;
import fileHandling.language.interfaces.SpawnMenuText;
import fileHandling.language.properties.NodeProps;

public class HunterSelectContent extends CustomizeContainer<HunterProperties> {
	
	private CustomizeWindow costumWindow;
	private String selectedHunter, boughtHunter;
	private InterfaceButton buyButton;
	private HorizontalScrollContent<HunterButton> hunterScrollContent;
	private ImageUpdater hunterPreview;
	private int previewSize, previewX, previewY;
	private HunterInfoContent infoContent;
	private HashMap<String, Hunter> availableHunters;
	private String buyString, sellString;
	private HunterDetailsContent hunterDetailsContent;
	
	public HunterSelectContent(Team team, int width, int height, CustomizeWindow costumWindow) {
		super(team, width, height);
		this.costumWindow = costumWindow;
		
		maxValues = team.getMaxHunterValues();
				
		availableHunters = new HashMap<String, Hunter>();
		
		initBuyButtonStrings();
		
		createBuyButton();
		makeHunterSelection();
		initPreview();
		createInfoLabels();
		
		InitGame.get().addLanguageListener(new LanguageListener() {
			@Override
			public void languageChanged() {
				changeLanguage();
			}
		});
		
		layout();
	}
	
	private void initBuyButtonStrings() {
		buyString = LanguageLoader.get(SpawnMenuText.Buy_Hunter);
		sellString = LanguageLoader.get(SpawnMenuText.Sell_Hunter);
	}
	
	private void createBuyButton() {
		buyButton = new InterfaceButton(buyString, GUISource.bigFont);
		buyButton.addButtonPressedListener(new IButtonPressedListener() {
			@Override
			public void buttonPressed(ButtonPressedEvent e) {
				if(selectedHunter.equals(boughtHunter)) {
					boughtHunter = null;
					costumWindow.getPlayer().addMoney(hunter.getHunterProperties().getCosts());
					costumWindow.getPlayer().removeHunter();
					hunter = null;
					changeInfoContent(selectedHunter, true);
					costumWindow.changeHunter(null);
				} else {
					boughtHunter = selectedHunter;
					
					DummyType dummyType = DummyType.None;
					if(!InitGame.get().isServer()) dummyType = DummyType.OnlyCollision;
					
					hunter = HunterFactory.createNewHunter(boughtHunter, team, dummyType);
					costumWindow.getPlayer().spendMoney(hunter.getHunterProperties().getCosts());
					costumWindow.changeHunter(hunter);
					enableUpgradeButtons();
					hunter.setHunterProperties(infoContent.getProperties());
				}
				updateBuyButtonText();
				resetOtherProps();
				layout();
			}
		});
		buyButton.setSize(width / 2, height / 15);
		buyButton.setXY(width - buyButton.getWidth(), 0);
	}
	
	private void updateBuyButtonText() {
		assert(selectedHunter != null);
		String costString = " (" + availableHunters.get(selectedHunter).getMovableShipProperties().getCosts() + ")";
		if(selectedHunter.equals(boughtHunter)) buyButton.setText(sellString + costString);
		else buyButton.setText(buyString + costString);
		enableBuyButton(costumWindow.getPlayer().getMoney());
	}
	
	private void enableBuyButton(float newMoney) {
		if(selectedHunter != null && !selectedHunter.equals(boughtHunter)) {
			int costs = availableHunters.get(selectedHunter).getMovableShipProperties().getCosts();
			if(newMoney >= costs) {
				buyButton.setEnabled(true);
				GUISource.setTextColor(buyButton, Color.WHITE);
			} else {
				buyButton.setEnabled(false);
				GUISource.setTextColor(buyButton, Color.RED);
			}
		} else {
			buyButton.setEnabled(true);
			GUISource.setTextColor(buyButton, Color.WHITE);
		}
	}
	
	private void createInfoLabels() {
		ImageFont labelFont = GUISource.bigFont;
		int width = getWidth() - previewSize - (3 * border);
		int height = previewSize;
		int x = previewSize + (2 * border);
		int y = previewY;
		
		hunterDetailsContent = new HunterDetailsContent(width, height, labelFont);
		hunterDetailsContent.setXY(x, y);
	}
	
	private void makeHunterSelection() {
		int hunterSelectHeight = height / 15;
		hunterScrollContent = new HorizontalScrollContent<HunterButton>(width, hunterSelectHeight, 0, 0);
		hunterScrollContent.setY(height - hunterSelectHeight);
		
		border = width / 30;
		previewSize = width / 3;
		infoX = border;
		infoY = buyButton.getHeight();
		infoWidth = width - infoX * 2;
		infoHeight = height - hunterSelectHeight - previewSize - border * 4;
		
		Fraction fraction = team.getFraction();
		final String previewPath = "data/fractions/" + fraction.toString().toLowerCase() + "/ships/";
		ImageFont buttonFont = GUISource.middleFont;
		int hunterButtonWidth = hunterScrollContent.getViewWidth() / 2;
		hunterScrollContent.setElementWidth(hunterButtonWidth);
		int hunterButtonHeight = hunterScrollContent.getHeight();
		Color color1 = Color.LIGHT_GRAY;
		Color color2 = Color.LIGHT_GRAY;
		Color c = color1;
		
		for(final String hunterName : team.getAvailableHunters()) {
			Hunter hunter = loadHunter(hunterName);
			HunterButton hunterButton = new HunterButton(hunterButtonWidth, hunterButtonHeight, hunter, fraction, buttonFont, c);
			hunterButton.addButtonListener(new IButtonPressedListener() {
				@Override
				public void buttonPressed(ButtonPressedEvent e) {
					if(hunterName.equals(selectedHunter)) return;
					selectedHunter = hunterName;
					if(!getContent().contains(buyButton)) addWidget(buyButton);
					changePreview(previewPath + selectedHunter + "/");
					
					if(!selectedHunter.equals(boughtHunter)) changeInfoContent(selectedHunter, false);
					else enableUpgradeButtons();
					updateBuyButtonText();
					layout();
				}
			});
			hunterScrollContent.addElement(hunterButton);
			
			c = c == color1 ? color2 : color1;
		}
		addWidget(hunterScrollContent);
		
		Hunter hunter = availableHunters.get(team.getAvailableHunters().get(0));
		HunterProperties props = hunter.getHunterProperties();
		HashMap<Lang, String[]> keys = new HashMap<Lang, String[]>();
		keys.put(NodeProps.MaxHP, new String[] { NodeProps.MaxHP.toString() });
		keys.put(NodeProps.MaxShields, new String[] { NodeProps.MaxShields.toString() });
		keys.put(NodeProps.MaxEnergy, new String[] { NodeProps.MaxEnergy.toString() });
		keys.put(NodeProps.Speed, new String[] { NodeProps.MaxForwardSpeed.toString(), 
												 NodeProps.MaxBoostSpeed.toString() });
		keys.put(NodeProps.Agility, new String[] { NodeProps.MaxTurnSpeed.toString() });
		keys.put(NodeProps.CounterMeasures, new String[] { NodeProps.CM_Efficiency.toString(), 
				 								 		   NodeProps.CM_ReloadTime.toString() });
		
		List<Lang> order = new ArrayList<Lang>();
		order.add(NodeProps.MaxHP);
		order.add(NodeProps.MaxShields);
		order.add(NodeProps.MaxEnergy);
		order.add(NodeProps.Speed);
		order.add(NodeProps.Agility);
		order.add(NodeProps.CounterMeasures);
		
		infoContent = new HunterInfoContent(infoWidth, infoHeight, infoX, infoY, props, maxValues, keys, 
				order, costumWindow.getPlayer());
	}
	
	private Hunter loadHunter(String hunterName) {
		Hunter hunter = HunterFactory.createNewHunter(hunterName, team, DummyType.Full);
		if(hunter != null) availableHunters.put(hunterName, hunter);
		return hunter;
	}
	
	private void changeInfoContent(String hunterName, boolean initUpgrades) {
		HunterProperties props = availableHunters.get(hunterName).getHunterProperties();
		if(!initUpgrades) props.resetLevel();
		if(!getContent().contains(infoContent)) addWidget(infoContent);
		infoContent.setProperties(props);
		infoContent.initUpgrades(initUpgrades);
		updateLabels(hunterName);
	}
	
	private void resetOtherProps() {
		for(Hunter hunter : availableHunters.values()) {
			if(this.hunter != null && hunter.getHunterProperties() == this.hunter.getHunterProperties()) 
				continue;
			hunter.getHunterProperties().resetLevel();
		}
	}
	
	private void updateLabels(String hunterName) {
		if(!hunterDetailsContent.isInit()) addWidget(hunterDetailsContent);
		
		Hunter hunter = availableHunters.get(hunterName);
		hunterDetailsContent.init(hunter);
	}
	
	private void enableUpgradeButtons() {
		changeInfoContent(boughtHunter, true);
	}
	
	private void initPreview() {
		previewX = border;
		previewY = hunterScrollContent.getY() - previewSize - border;
		hunterPreview = new ImageUpdater(previewX, previewY, previewSize, previewSize);
		addWidget(hunterPreview);
	}
	
	private void changePreview(String hunterPath) {
		hunterPath += BBNodeController.ICON_FILE;
		
		hunterPreview.setImage(hunterPath);
		
		layout();
	}
	
	@Override
	public void changeHunter(Hunter hunter) {
		if(this.hunter == hunter) return;
		
		boughtHunter = hunter.getName();
		
		for(HunterButton button : hunterScrollContent.getElements()) {
			if(button.getHunterName().equals(boughtHunter)) {
				int x = button.getX() + button.getWidth() / 2;
				int y = button.getY() + button.getHeight() / 2;
				Set<Key> set = new HashSet<Key>();
				MousePressedEvent press = new MousePressedEvent(button, x, y, MouseButton.LEFT, 1, set);
				button.mousePressed(press);
				MouseReleasedEvent release = new MouseReleasedEvent(button, x, y, MouseButton.LEFT, 1, set);
				button.mouseReleased(release);
				break;
			}
		}
	}
	
	@Override
	public void updateMoney(int newMoney) {
		infoContent.updateMoney(newMoney);
		enableBuyButton(newMoney);
	}
	
	public void changeLanguage() {
		initBuyButtonStrings();
		
		if(selectedHunter != null) {
			updateBuyButtonText();
			updateLabels(selectedHunter);
		}
	}
	
	@Override
	public void restore() {
		Player player = costumWindow.getPlayer();
		Hunter hunter = player.getHunter();
		
		if(hunter != null) {
			String hunterName = hunter.getName();
			availableHunters.put(hunterName, hunter);
			
			boughtHunter = hunterName;
			
			for(HunterButton button : hunterScrollContent.getElements()) {
				if(button.getHunterName().equals(hunterName)) {
					int x = button.getX();
					int y = button.getY();
					MouseButton mouseButton = MouseButton.LEFT;
					Set<Key> set = new HashSet<Key>();
					MouseClickedEvent mce = new MouseClickedEvent(button, x, y, mouseButton, 1, set);
					button.mouseClicked(mce);
					break;
				}
			}
		}
	}
	
	public HorizontalScrollContent<HunterButton> getHunterScrollContent() { return hunterScrollContent; }
}